//给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集，使得两个子集的元素和相等。 
//
// 
//
// 示例 1： 
//
// 
//输入：nums = [1,5,11,5]
//输出：true
//解释：数组可以分割成 [1, 5, 5] 和 [11] 。 
//
// 示例 2： 
//
// 
//输入：nums = [1,2,3,5]
//输出：false
//解释：数组不能分割成两个元素和相等的子集。
// 
//
// 
//
// 提示： 
//
// 
// 1 <= nums.length <= 200 
// 1 <= nums[i] <= 100 
// 
// Related Topics 数组 动态规划 👍 1319 👎 0

package leetcode.editor.cn;

//leetcode submit region begin(Prohibit modification and deletion)
class Solution416 {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        if (sum % 2 != 0) return false;
        int target = sum / 2;
        int[] dp = new int[target + 1];
        for(int i = 0; i < nums.length; i++){
            for(int j = target; j >= nums[i]; j--){
                dp[j] = Math.max(dp[j], dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[target] == target;
    }

        /**
         * 一维数组，使用true, false
         * @param nums
         * @return
         */
    public boolean canPartition2(int[] nums) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        if (sum % 2 != 0) return false;
        int target = sum / 2;
        boolean[] dp = new boolean[target+1];
        for (int i = 0; i < nums.length; i++) {
            for (int j = target; j >= nums[i]; j--) {
                if(nums[i] == j) dp[j] = true;  //初始化
                 else dp[j] = dp[j] || dp[j-nums[i]];
            }
        }
        return dp[target];
    }
        /**
         * 采用二维数组，使用true, false
         *
         * @param nums
         * @return
         */
    public boolean canPartition1(int[] nums) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        if (sum % 2 != 0) return false;
        int target = sum / 2;
        //dp[i][j]表示从nums[0]~nums[i]中取出的数是否等于j
        boolean[][] dp = new boolean[nums.length][target + 1];
        //初始化
        for (int j = 0; j <= target; j++) {
            if (nums[0] == j) {
                dp[0][j] = true;
            }
        }
        for (int i = 1; i < nums.length; i++) {
            for (int j = 0; j <= target; j++) {
                if (j > nums[i]) { //可以装的下第i个物品
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]];
                } else { //装不下第i个物品
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[nums.length - 1][target];
    }

    public static void main(String[] args) {
        new Solution416().canPartition(new int[]{1, 5, 11, 5});
    }
}
//leetcode submit region end(Prohibit modification and deletion)
